/*
s[i]=s[j] && (i-j)%2==0 -> 位置奇偶性相同的字符数量相同
第一点：考虑怎么分配字母，对于所有字母完全背包

第二点：odd!*even!/(累乘(1~n)c[i])

odd!*even!*dp[odd]/(累乘(1~n)c[i]) 奇数确定后偶数自动确定
*/
#include <cstdio> 
#include <cstring>
using namespace std;
template <typename T>
inline void read(T& x)
{
    int c=getchar(), f=1; x=0;
    while(c<'0'||'9'<c) {if(c=='-') f=-1; c=getchar();}
    while('0'<=c&&c<='9') 
        x=(x<<3)+(x<<1)+c-'0', c=getchar();
    x*=f;
}

inline void write(long long x)
{
    if(x>=10) write(x/10);
    putchar(x%10+'0');
}
#define DEBUG
#define mod(x) ((x%MOD+MOD)%MOD)
using ll=long long;
const int N=5e5+10, MOD=998244353;
int n=26;
ll c[30];
ll dp[N]; //dp[j]使用前i个字母，恰好填满j个奇数位置
ll sum;

inline ll qmi(int base, int index)
{
    ll ret=1;
    while(index)
    {
        if(index&1) ret=mod(ret*base);
        index>>=1;
        base=mod(1ll*base*base);
    }
    return ret;
}

inline ll fact(int x)
{
    ll ret=1;
    for(int i=1; i<=x; i++)
        ret=mod(ret*i);
    return ret;
}

void init()
{
    sum=0;
    for(int i=1; i<=n; i++) read(c[i]), sum+=c[i];
    memset(dp, 0, sizeof dp);
    dp[0]=1; //前0个字母填满0个位置有1种方案
}

void solve()
{
    init();
    for(int i=1; i<=26; i++)
    {
        if(c[i]==0) continue;
        for(ll j=sum; j>=0; j--) //枚举背包容量
            if(j+c[i]<=sum) dp[j+c[i]]=mod(dp[j+c[i]]+dp[j]);
    }

    ll ans=mod(mod(dp[sum>>1]*fact(sum>>1))*mod(fact((sum+1)>>1)));

    for(int i=1; i<=26; i++) 
    {
        if(c[i]==0) continue;
        ans=mod(ans*qmi(fact(c[i]), MOD-2)); //除去相同字母的排列->除fact(c[i])
    }
    write(ans); puts("");
}

// #undef DEBUG
signed main()
{
    #ifdef DEBUG
        freopen("../in.txt", "r", stdin);
        freopen("../out.txt", "w", stdout);
    #endif

    int T=1; scanf("%d", &T);
    while(T--) 
    {
        solve();
    }
    return 0;
}